/************************************************************************
This file is part of Polar4linux
Copyright (C) 2010-2011 Eric jrdn2
Portions Copyright (C) 2007 Matti Juvonen <mpj@iki.fi> (RS400 Tools)
Portions Copyright (C) 2006 Jani Hursti <jani.hursti@hut.fi>,
Portions Copyright (C) 2001-2003 Tom Oliveira e Silva

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
************************************************************************/

#include <stdio.h>

#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include "RS400_comm.h"
#include <sys/time.h>
#include <signal.h>
#include <setjmp.h>

static int rs400_comm_fd;

/* Send raw bytes to the device. Return the number of bytes written */
int RS400_sendbytes(const unsigned char query[], int size)
{
	printf("send frame of size=%d\n",size);
	int sent=write(rs400_comm_fd, query, size);
	return sent;
}

/* Receive raw bytes from the device. Returns the number of bytes read */
/* Note that it's the caller's duty to clear the receive buffer */
int RS400_recvbytes(unsigned char buf[])
{
	int recv=read(rs400_comm_fd, buf, RS400_MAX_PACKET_SIZE);
	printf("\trecv frame of size=%d\n",recv);
	return recv;
}

 
sigjmp_buf contexteAlarme;
 
void gestionAlarme(int /*numSig*/) {
  siglongjmp( contexteAlarme, 1); /* branchement a sigsetjmp() en retournant 1 */
}
 
int RS400_init(char socket[],int timeoutvalue)
{
	signal(SIGALRM,gestionAlarme); 
	if (!sigsetjmp(contexteAlarme, 1))
	{
		/* 1er passage */
		alarm(timeoutvalue);     /* Mise en place du timer */
		rs400_comm_fd = open(socket, O_RDWR );
		if (rs400_comm_fd < 0)
		{
			perror(socket);
			exit(1);
		}
		alarm(0);  //connexion ok
		struct termios tio;
		memset(&tio, 0, sizeof(tio));
		tio.c_cflag = B38400 | CS8 | CLOCAL | CREAD | CSTOPB;
		tio.c_iflag = IGNPAR;
		tio.c_oflag = 0;
		tio.c_lflag = 0;
		tio.c_cc[VTIME] = 100;
		tio.c_cc[VMIN] = 0;

		tcflush(rs400_comm_fd, TCIOFLUSH);
		tcsetattr(rs400_comm_fd, TCSANOW, &tio);

		printf("Opened socket %s\n", socket);
		return (1);
  }
  return(0);
}


//opens irda port, returns 1 if connexion is ok
int init_session(std::string chaine0,int timeoutvalue)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	//char chaine[]=chaine0.c_str();
	int socState=RS400_init((char*)chaine0.c_str(),timeoutvalue);
	if (socState==1)
	{
		unsigned char query[] = { 0x00, 0x0E };
		RS400_sendbytes(query, sizeof(query));
		RS400_recvbytes(buf);
	}
	return socState;
}

int RS400_watchmode()
{
	unsigned char query[] = { RS400_CMD_WATCHMODE };
	return RS400_sendbytes(query, sizeof(query));
}

int RS400_sleepmode()
{
	unsigned char query[] = { RS400_CMD_SLEEPMODE };
	return RS400_sendbytes(query, sizeof(query));
}

int RS400_get_overview(unsigned char data[])
{
	unsigned char query[] = { RS400_CMD_GETOVERVIEW };
	RS400_sendbytes(query, sizeof(query));
	return RS400_recvbytes(data);
}

int RS400_factoryreset()
{
	unsigned char query[] = { RS400_CMD_FACTORYRESET };
	return RS400_sendbytes(query, sizeof(query));
};

int RS400_get_session(char id, unsigned char data[])
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	int pos = 0;
	unsigned char query1[] = { RS400_CMD_GETSESSION, id, 0x00, 0x00 };
	RS400_sendbytes(query1, sizeof(query1));
	int size = RS400_recvbytes(buf) - 4; /* Skip first 4 bytes of header */

	memcpy(data, buf + 4, size);
	unsigned char query2[] = { RS400_CMD_CONTINUEXFER, id };
	pos = size;
	RS400_sendbytes(query2, sizeof(query2));
	size = RS400_recvbytes(buf) - 5; // Skip first 5 bytes of header */
	while(size > 2)
	{
		memcpy(data + pos, buf + 5, size);
		pos += size;
		RS400_sendbytes(query2, sizeof(query2));
		size = RS400_recvbytes(buf) - 5;
	}
	return pos; /* Contains final size of the session file */
}


int RS400_close()
{
	return close(rs400_comm_fd);
}

void RS400_separate()
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char finish[] ={0x58};
	RS400_sendbytes(finish, sizeof(finish));
	RS400_recvbytes(buf);
}

//set the watch to idle and close port
void RS400_close_session()
{
	RS400_separate();
	RS400_watchmode();
	RS400_close();
}

//send user properties to the watch
void _setUSER(polarLINUXio_user const &u)
{
	//sex is encoded for the watch ie +0x38
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char WeightLSB,WeightMSB;
	weighKG_to_msb_lsb(u.weight,&WeightMSB,&WeightLSB);
	
	unsigned char frame[]=	{	0x59,0xAC,0x00,0x00,0x7E,0x01,0x00,0x00,
	WeightLSB,WeightMSB,u.height,u.birth_day,u.birth_month,u.birth_year,
	u.FCmax,u.VO2max,u.FCmin,u.sex+0x38,u.activity_level,0x01,0x00,0x00};
	
	RS400_sendbytes(frame, sizeof(frame));
	RS400_recvbytes(buf);
	
	RS400_separate();
}

//get user properties from the watch
void _getUSER(polarLINUXio_user &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char query[] ={0x5A, 0x00, 0x7E, 0x01, 0x00, 0x00, 0x0E, 0x00}; //user weight, eight etc...
	RS400_sendbytes(query, sizeof(query));
	RS400_recvbytes(buf);

	u.weight=msb_lsb_to_weighKG(buf[6], buf[7]);
	u.height=buf[8];
	u.birth_day=buf[9];
	u.birth_month=buf[10];
	u.birth_year=buf[11];
	u.FCmax=buf[12];
	u.VO2max=buf[13];
	u.FCmin=buf[14];

	//guys can't decide if a man is 0x38(watch) or 0x1E(polartrainer)
	if (buf[15]==0x1E || buf[15]==0x38) u.sex=0; //guy
	else if (buf[15]==0x1F || buf[15]==0x39) u.sex=1;
	u.activity_level=buf[16]; 
}


void _setPlayer(polarLINUXio_player const &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char commandCAT0[29];
	unsigned char command[]={ 0x59,0xAC,0x00,0x00,0xA2,0x01,0x00,0x00};

	memcpy(commandCAT0,command,sizeof(command));
	rs400_encode_string(commandCAT0+8,u.first_name,10);
	rs400_encode_string(commandCAT0+18,u.last_name,10);
	commandCAT0[28]=u.player_number;
	RS400_sendbytes(commandCAT0, sizeof(commandCAT0));
	RS400_recvbytes(buf);
	
	//magic number?
	//displays tshirts with player number and player name
	unsigned char fourscreen[]={0x59,0xAC,0x00,0x00,0x95,0x01,0x00,0x00,0x40};
	RS400_sendbytes(fourscreen, sizeof(fourscreen));
	RS400_recvbytes(buf);
	
	unsigned char next[]={0x59,0xAC,0x00,0x00,0x90,0x01,0x00,0x00,0x00};
	RS400_sendbytes(next, sizeof(next));
	RS400_recvbytes(buf);
	
	RS400_separate();
}

void _getPlayer(polarLINUXio_player &u)
{
	unsigned char frame[] ={0x5A, 0x00, 0xA2, 0x01, 0x00, 0x00, 0x15, 0x00}; //getUser names and player number
	unsigned char buf[RS400_MAX_PACKET_SIZE];

	RS400_sendbytes(frame, sizeof(frame));
	RS400_recvbytes(buf);

	rs400_decode_string(u.first_name,buf+6,10);
	rs400_decode_string(u.last_name,buf+16,10);
	u.player_number=buf[26];
	
	//override uninitialized values
	if (strcmp((char*)u.first_name,"0000000000\0")==0) strncpy((char*)u.first_name,"firstname \0",11);
	if (strcmp((char*)u.last_name,"0000000000\0")==0) strncpy((char*)u.last_name,"lastname \0",11);
	if (u.player_number==0) u.player_number=1;
}


void _setDisplay(polarLINUXio_general_settings const &u0)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];

	const polarLINUXio_display *uSP=&u0.displaywSpeed;
	const polarLINUXio_display *u=&u0.displaywoSpeed;
	unsigned char ActiveDisplaysSpeed=0x01+uSP->display2activated*0x02+uSP->display3activated*0x04+uSP->display4activated*0x08+uSP->display5activated*0x10;
	unsigned char ActiveDisplays=0x19+u->display2activated*0x02+u->display3activated*0x04;

	
	unsigned char frameSP[]={0x59,0xAC,0x00,0x00,0x74,0x03,0x00,0x00,ActiveDisplaysSpeed,ActiveDisplays,
	uSP->display1up,uSP->display2up,uSP->display3up,uSP->display4up,uSP->display5up,uSP->display6up,
	uSP->display1middle,uSP->display2middle,uSP->display3middle,uSP->display4middle,uSP->display5middle,uSP->display6middle,
	uSP->display1down,uSP->display2down,uSP->display3down,uSP->display4down,uSP->display5down,uSP->display6down};

	unsigned char frame[]={0x59,0xAC,0x00,0x00,0x88,0x03,0x00,0x00,
	u->display1up,u->display2up,u->display3up,u->display4up,u->display5up,u->display6up,
	u->display1middle,u->display2middle,u->display3middle,
	u->display4middle,u->display5middle,u->display6middle,
	u->display1down,u->display2down,u->display3down,u->display4down,u->display5down,u->display6down};

	//displaybuf(frameSP,50);
	
	RS400_sendbytes(frameSP, sizeof(frameSP));
	RS400_recvbytes(buf);
	
	RS400_sendbytes(frame, sizeof(frame));
	RS400_recvbytes(buf);

	RS400_separate();
}

void _getDisplay(polarLINUXio_general_settings &u0)
{
	polarLINUXio_display *u;
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	//4) display
	unsigned char query6[] ={0x5A, 0x00, 0x74, 0x03, 0x00, 0x00, 0x50, 0x00};
	RS400_sendbytes(query6, sizeof(query6));
	RS400_recvbytes(buf);

	u=&u0.displaywSpeed;
	u->display1up=buf[8]; 
	u->display1middle= buf[14]; 
	u->display1down=buf[20]; 

	u->display2up=buf[9];
	u->display2middle= buf[15]; 
	u->display2down=buf[21];

	u->display3up=buf[10];
	u->display3middle= buf[16]; 
	u->display3down=buf[22];

	u->display4up=buf[11];
	u->display4middle= buf[17]; 
	u->display4down=buf[23];

	u->display5up=buf[12];
	u->display5middle= buf[18]; 
	u->display5down=buf[24];
	
	u->display6up=buf[13];
	u->display6middle=buf[19]; 
	u->display6down=buf[25];
	
	u->display2activated = (buf[6] & 0x02) >> 1;
	u->display3activated = (buf[6] & 0x04) >> 2;
	u->display4activated = (buf[6] & 0x08) >> 3;
	u->display5activated = (buf[6] & 0x10) >> 4;

	u=&u0.displaywoSpeed;
	u->display1up=buf[26]; 
	u->display1middle= buf[32]; 
	u->display1down=buf[38]; 

	u->display2up=buf[27];
	u->display2middle= buf[33]; 
	u->display2down=buf[39];

	u->display3up=buf[28];
	u->display3middle= buf[34]; 
	u->display3down=buf[40];

	u->display4up=buf[29];
	u->display4middle=buf[35]; 
	u->display4down=buf[41];

	u->display5up=buf[30];
	u->display5middle=buf[36]; 
	u->display5down=buf[42];

	u->display6up=buf[31];
	u->display6middle=buf[37]; 
	u->display6down=buf[43];
	u->display2activated = ((buf[7]-0x19) & 0x02) >> 1;
	u->display3activated = ((buf[7]-0x19) & 0x04) >> 2;
	u->display4activated = 0;
	u->display5activated = 0;
}


void _setGeneralSettings(polarLINUXio_general_settings const &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char m,l;

	//1) keyboard
	unsigned char keyboard=u.autoLock*0x01+u.optionsLock*0x02+!u.zoneWarning*0x04+u.showScreenName*0x08+u.units*0x10;

	unsigned char trame0[]={0x66, keyboard, u.bipButton, u.hearttouch, u.language};
	RS400_sendbytes(trame0, sizeof(trame0));
	RS400_recvbytes(buf);

	//2) shoes
	unsigned char sh1[9],sh2[9];
	rs400_encode_string(sh1,u.sh1,9);
	rs400_encode_string(sh2,u.sh2,9);

	unsigned char result=0x40*u.shoes+0x01*u.measureSpeed+u.speedOrPace*0x02+u.autolap*0x04+u.HRFormat*0x10+u.estimatedFCMax*0x08;

	int sample = 0;
	if (u.sampleRate==0) sample = 199;
	else if (u.sampleRate==1) sample = 203;
	else if (u.sampleRate==2) sample = 211;
	else sample = 227;

	int_to_msb_lsb(u.calibration,&m,&l);
	unsigned char trame[]={ 0x59,0xAC,0x00,0x00,0x52,0x02,0x00,0x00,
	result,0xA0,u.autolapDistance,0x00,0x00,0x05,u.sportZvalues[0],u.sportZvalues[1],
	u.sportZvalues[2],u.sportZvalues[3],u.sportZvalues[4],u.sportZvalues[5],0x00,0x00,0x00,0x00,
	0x00,0x01,l,m,0x01,sh1[0],sh1[1],sh1[2],
	sh1[3],sh1[4],sh1[5],sh1[6],sh1[7],sh1[8],0,sh2[0],
	sh2[1],sh2[2],sh2[3],sh2[4],sh2[5],sh2[6],sh2[7],sh2[8],
	0,sample};

	RS400_sendbytes(trame, sizeof(trame));
	RS400_recvbytes(buf);

	//kms and date of the shoes
	//first we need to ask how are other parameters before writing only kms and dates
	//because we only change a few of them
	//we take these in the stats, change them, and rewrite the stats
	unsigned char askF[] ={0x5A, 0x00, 0xBE, 0x03, 0x00, 0x00, 0x57, 0x00}; //stats
	RS400_sendbytes(askF, sizeof(askF));
	RS400_recvbytes(buf);

	unsigned char ask2[]={0x59,0xAC,0x00,0x00,0xBE,0x03,0x00,0x00};
	unsigned char trame002[43];
	memcpy(trame002,ask2,8);
	memcpy(trame002+10,buf+8,33);

	char km1[2],km2[2];
	km1[1] = decimal_to_same_hexa(u.sh1km/100); km1[0]=decimal_to_same_hexa(u.sh1km%100);
	km2[1] = decimal_to_same_hexa(u.sh2km/100); km2[0]=decimal_to_same_hexa(u.sh2km%100);

	trame002[31]=km1[0];
	trame002[32]=km1[1];
	trame002[37]=km2[0];
	trame002[38]=km2[1];

	ddmmyy2hex(u.sh1date[0],u.sh1date[1],u.sh1date[2],&trame002[34],&trame002[35]);
	ddmmyy2hex(u.sh2date[0],u.sh2date[1],u.sh2date[2],&trame002[40],&trame002[41]);

	RS400_sendbytes(trame002, sizeof(trame002));
	RS400_recvbytes(buf);


	//3) lockON
	unsigned char trame2[]={0x59,0xAC,0x00,0x00,0xE4,0x03,0x00,0x00,u.lockON,0x0F,u.lockONpaceValue};
	RS400_sendbytes(trame2, sizeof(trame2));
	RS400_recvbytes(buf);

	RS400_separate();
}



void _getGeneralSettings(polarLINUXio_general_settings &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	//1) sportzones, etc
	unsigned char query5[] ={0x5A, 0x00, 0x52, 0x02, 0x00, 0x00, 0x35, 0x00}; 
	RS400_sendbytes(query5, sizeof(query5));
	RS400_recvbytes(buf);

	u.sportZvalues[0]=buf[12];
	u.sportZvalues[1]=buf[13];
	u.sportZvalues[2]=buf[14];
	u.sportZvalues[3]=buf[15];
	u.sportZvalues[4]=buf[16];
	u.sportZvalues[5]=buf[17];

	u.measureSpeed=   (buf[6] & 0x01);
	u.speedOrPace=    (buf[6] & 0x02) >> 1;
	u.autolap=        (buf[6] & 0x04) >> 2;
	u.estimatedFCMax= (buf[6] & 0x08) >> 3;
	u.HRFormat=       (buf[6] & 0x10) >> 4;
	u.shoes=          (buf[6] & 0x40) >> 6;

	u.autolapDistance = buf[8];
	u.calibration = msb_lsb_to_decimal(buf[25],buf[24]);
	rs400_decode_string(u.sh1,&buf[27],9);
	rs400_decode_string(u.sh2,&buf[37],9);

	//sample rate

	int sample = buf[47];

	if (sample%2!=0) //default watch values
	{
		if (sample==255 || sample == 199) u.sampleRate = 0;
		else if (sample == 203) u.sampleRate = 1;
		else if (sample == 211) u.sampleRate = 2;
		else u.sampleRate = 3;
	}
	else //polartrainer values
	{
		int row = 0;
		while (sample !=2)
		{
			sample/=2;
			row+=1;
		}
		u.sampleRate=row;
	}



	//2) //distance and date of the shoes, and pace lock
	unsigned char query12[] ={0x5A, 0x00, 0xD4, 0x03, 0x00, 0x00, 0x32, 0x00};
	RS400_sendbytes(query12, sizeof(query12));
	RS400_recvbytes(buf);

	u.lockON=buf[22];
	u.lockONpaceValue=buf[24];

	u.sh1km = hexa_to_same_decimal(buf[7])+100*hexa_to_same_decimal(buf[8]);
	u.sh2km = hexa_to_same_decimal(buf[13])+100*hexa_to_same_decimal(buf[14]);
	hex2ddmmyy(buf[10],buf[11],&u.sh1date[0],&u.sh1date[1],&u.sh1date[2]);
	hex2ddmmyy(buf[16],buf[17],&u.sh2date[0],&u.sh2date[1],&u.sh2date[2]);

	//3) keyboard
	unsigned char trame[] ={0x5A, 0x00, 0x8C, 0x01, 0x00, 0x00, 0x04, 0x00};
	RS400_sendbytes(trame, sizeof(trame));
	RS400_recvbytes(buf);

	u.units = (buf[6] & 0x10) >> 4;
	u.showScreenName = (buf[6] & 0x08) >> 3; 
	u.zoneWarning = !((buf[6] & 0x04) >> 2);
	u.optionsLock = (buf[6] & 0x02) >> 1;
	u.autoLock = (buf[6] & 0x01);
	u.bipButton = buf[7];
	u.hearttouch = buf[8];
	u.language = buf[9];

}




void _setDateAndTime(polarLINUXio_general_settings const &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];

	char WUminute = decimal_to_same_hexa(u.wakeUpMin);
	char WUhour =   decimal_to_same_hexa(u.wakeUpHour);

	//command duplication
	unsigned char trame[]={0x5B,0x13,0x0A,0x08,0x47,0x34,0x19,0x08,0x00,WUminute,WUhour,u.wakeUpOn};
	RS400_sendbytes(trame, sizeof(trame));
	RS400_recvbytes(buf);

	char second = decimal_to_same_hexa(u.second);
	char minute = decimal_to_same_hexa(u.minute);
	char hour =   decimal_to_same_hexa(u.hour);
	unsigned char currentfuse=0;
	unsigned char fuseanddisp=0x18+u.display12h+currentfuse*0xc6; //+0x20*u.event.isActive
	unsigned char setTime[]={0x5b,u.day,u.month,u.year,second,minute,hour,fuseanddisp,u.shift_fuse2,WUminute,WUhour,u.wakeUpOn};

	RS400_sendbytes(setTime, sizeof(setTime));
	RS400_recvbytes(buf);
	
	RS400_separate();
}


void _getDateAndTime(polarLINUXio_general_settings &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];

	unsigned char t18[]={0x5A,0x00,0x90,0x01,0x00,0x00,0x1E,0x00}; 

	RS400_sendbytes(t18, sizeof(t18));
	RS400_recvbytes(buf);
	std::cout<<"buf7="<<(int)buf[7]<<std::endl;
	u.shift_fuse2=buf[7];
	u.wakeUpMin=hexa_to_same_decimal(buf[8]);
	u.wakeUpHour=hexa_to_same_decimal(buf[9]);
	u.wakeUpOn=buf[10];
	//std::cout<<"buf11="<<std::hex<<(int)buf[11]<<std::endl;
	//i think i don't get the point on a specific parameter
	if (buf[11]%2!=0) u.display12h=1; else u.display12h=0;
}



void _setStats(polarLINUXio_general_settings const &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];

	unsigned char hoursTotal =    decimal_to_same_hexa(u.hoursTotal);
	unsigned char minutesTotal =  decimal_to_same_hexa(u.minutesTotal);
	unsigned char exerciseTotal = decimal_to_same_hexa(u.exerciseTotal);

	unsigned char caloriesTotal[2];
	unsigned char kmsh1[2];
	unsigned char kmsh2[2];
	unsigned char kmTot[2];

	//ascension?????????
	int_to_msb_lsb(decimal_to_same_hexa(u.caloriesTotal), &caloriesTotal[1], &caloriesTotal[0]);
	int_to_msb_lsb(decimal_to_same_hexa(u.sh1km), &kmsh1[1], &kmsh1[0]);
	int_to_msb_lsb(decimal_to_same_hexa(u.sh2km), &kmsh2[1], &kmsh2[0]);
	int_to_msb_lsb(decimal_to_same_hexa(u.Totaldistance), &kmTot[1], &kmTot[0]);


	//note duration : 0x10 0x01 affiche 1h10
	//note distance  // 0x19 0x10 affiche 1019 km 
	unsigned char trame[]=
	{0x59,0xAC,0x00,0x00,0xBE,0x03,0x00,0x00,0x00,
	minutesTotal,hoursTotal,0x00,0x00,0x00,
	caloriesTotal[0],caloriesTotal[1],0x00,0x00,0x00,0x00,
	exerciseTotal,0x00,0x00,0x00,0x00,
	kmTot[0],kmTot[1],0x00,0x00,0x00,0x00,
	kmsh1[0],kmsh1[1],0x00,0x00,0x00,0x00,
	kmsh2[0],kmsh2[1],0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

	ddmmyy2hex(u.dateTotalDuration[0],u.dateTotalDuration[1],u.dateTotalDuration[2],&trame[12],&trame[13]);
	ddmmyy2hex(u.dateTotalCalories[0],u.dateTotalCalories[1],u.dateTotalCalories[2],&trame[18],&trame[19]);
	ddmmyy2hex(u.dateTotalExercises[0],u.dateTotalExercises[1],u.dateTotalExercises[2],&trame[22],&trame[23]);
	ddmmyy2hex(u.dateTotaldistance[0],u.dateTotaldistance[1],u.dateTotaldistance[2],&trame[28],&trame[29]);
	ddmmyy2hex(u.dateshoes1[0],u.dateshoes1[1],u.dateshoes1[2],&trame[34],&trame[35]);
	ddmmyy2hex(u.dateshoes2[0],u.dateshoes2[1],u.dateshoes2[2],&trame[40],&trame[41]);

	RS400_sendbytes(trame, sizeof(trame));
	RS400_recvbytes(buf);
	
	RS400_separate();
}



void _getStats(polarLINUXio_general_settings &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char query14[] ={0x5A, 0x00, 0xBE, 0x03, 0x00, 0x00, 0x57, 0x00}; //stats, cumul

	RS400_sendbytes(query14, sizeof(query14));
	RS400_recvbytes(buf);

	u.hoursTotal=hexa_to_same_decimal(buf[8]);
	u.minutesTotal=hexa_to_same_decimal(buf[7]);
	u.caloriesTotal=hexa_to_same_decimal(buf[12])+100*hexa_to_same_decimal(buf[13])+hexa_to_same_decimal(buf[14])*10000;
	u.exerciseTotal=hexa_to_same_decimal(buf[18])+100*hexa_to_same_decimal(buf[19]);
	u.Totaldistance=hexa_to_same_decimal(buf[23])+100*hexa_to_same_decimal(buf[24]);
	u.sh1km=hexa_to_same_decimal(buf[29])+100*hexa_to_same_decimal(buf[30]);
	u.sh2km=hexa_to_same_decimal(buf[35])+100*hexa_to_same_decimal(buf[36]);

	hex2ddmmyy(buf[10],buf[11],&u.dateTotalDuration[0],&u.dateTotalDuration[1],&u.dateTotalDuration[2]);
	hex2ddmmyy(buf[20],buf[21],&u.dateTotalExercises[0],&u.dateTotalExercises[1],&u.dateTotalExercises[2]);
	hex2ddmmyy(buf[16],buf[17],&u.dateTotalCalories[0],&u.dateTotalCalories[1],&u.dateTotalCalories[2]);
	hex2ddmmyy(buf[26],buf[27],&u.dateTotaldistance[0],&u.dateTotaldistance[1],&u.dateTotaldistance[2]);
	hex2ddmmyy(buf[32],buf[33],&u.dateshoes1[0],&u.dateshoes1[1],&u.dateshoes1[2]);
	hex2ddmmyy(buf[38],buf[39],&u.dateshoes2[0],&u.dateshoes2[1],&u.dateshoes2[2]);
}


void _setExos(polarLINUXio_exercises_list const &u)
{
	char t1[2],t2[2],t3[2];
	unsigned char msb,lsb;
	unsigned char buf[RS400_MAX_PACKET_SIZE]; //,frame1[5*53+8],frame2[5*53+8];

	char totalEx = u.totalnum;
	//tells the number of existing exercises to the watch
	unsigned char trame0[]={0x59,0xAC, 0x00, 0x00, 0xE7, 0x03, 0x00, 0x00, totalEx};
	RS400_sendbytes(trame0, sizeof(trame0));
	RS400_recvbytes(buf);

	RS400_separate();

	unsigned char name[11];
	unsigned char desc[21];


	unsigned char set1[]={0x59,0xAC,0x00,0x00,0xCB,0x08,0x00,0x00};//base addr
	int baseaddr=msb_lsb_to_decimal(0x08,0xCB);
	char envoi=0x01;
	for (int ii=0;ii<totalEx;ii++)
	{
		if (ii>=5) envoi = 0x00;
		int addr=baseaddr+53*ii;
		int_to_msb_lsb(addr, &msb, &lsb);
		set1[4]=lsb;
		set1[5]=msb;
		memcpy(buf,set1,sizeof(set1));
		const polarLINUXio_basic_exercise *p=&u.exo[ii];

		rs400_encode_string(name,(unsigned char*)p->name,10);
		rs400_encode_string(desc,(unsigned char*)p->description,20);

		//unsigned char zone = p->num_zones+p->active_zonesTargets*0x10;
		unsigned char zone = p->num_zones+ p->num_zones*0x10;
		
		unsigned char trame[]={envoi,ii,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\
		p->guideType,p->zones_type,zone,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

		memcpy(trame+2,name,10);
		memcpy(trame+12,desc,20);

		if (p->guideType==0 || p->guideType==1)
		{
			t1[0]=p->zone1length%100;
			t1[1]=p->zone1length/100;
			t2[0]=p->zone2length%100;
			t2[1]=p->zone2length/100;
			t3[0]=p->zone3length%100;
			t3[1]=p->zone3length/100;

			trame[35]=decimal_to_same_hexa(t1[0]);
			trame[36]=decimal_to_same_hexa(t1[1]);
			trame[37]=decimal_to_same_hexa(t2[0]);
			trame[38]=decimal_to_same_hexa(t2[1]);
			trame[39]=decimal_to_same_hexa(t3[0]);
			trame[40]=decimal_to_same_hexa(t3[1]);
		}
		else //if (p->guideType==2)
		{
			int_to_msb_lsb(p->zone1length,&trame[36],&trame[35]);
			int_to_msb_lsb(p->zone2length,&trame[38],&trame[37]);
			int_to_msb_lsb(p->zone3length,&trame[40],&trame[39]);
		}

		trame[41]=p->FC1min[0];
		trame[42]=p->FC1min[1];
		
		trame[43]=p->FC2min[0];
		trame[44]=p->FC2min[1];

		trame[45]=p->FC3min[0];
		trame[46]=p->FC3min[1];
		
		trame[47]=p->FC1max[0];
		trame[48]=p->FC1max[1];
		
		trame[49]=p->FC2max[0];
		trame[50]=p->FC2max[1];

		trame[51]=p->FC3max[0];
		trame[52]=p->FC3max[1];

		memcpy(buf+8,trame,sizeof(trame));

		RS400_sendbytes(buf, 53+8);
		RS400_recvbytes(buf);
	}
	
	RS400_separate();
}


void _getExos(polarLINUXio_exercises_list &u)
{
	int t1,t2,t3;

	int step;
	unsigned char buf[RS400_MAX_PACKET_SIZE],buf2[RS400_MAX_PACKET_SIZE];
	unsigned char query16[] ={0x5A, 0x00, 0xE7, 0x03, 0x00, 0x00, 0x05, 0x00}; //Number of exercises

	RS400_sendbytes(query16, sizeof(query16));
	RS400_recvbytes(buf);

	int numEx=buf[6];
	char ask1=0xF2,ask2=0xF2;

	if (numEx <5)
	{
		ask1 = 53*numEx;
	}

	if (numEx >=5 && numEx !=10)
	{
		ask2 = 23+53*(numEx-5);
	}

	unsigned char query17[] ={0x5A, 0x00, 0xCB, 0x08, 0x00, 0x00, ask1, 0x00}; //first 5 exercices
	unsigned char query18[] ={0x5A, 0x00, 0xBD, 0x09, 0x00, 0x00, ask2, 0x00}; //next 5 exercices

	RS400_sendbytes(query17, sizeof(query17));
	int sizeRECV = RS400_recvbytes(buf);

	RS400_sendbytes(query18, sizeof(query18));
	int sizeRECV2 = RS400_recvbytes(buf2);

	memcpy(buf+sizeRECV,buf2+6,sizeRECV2-6);

	u.totalnum = numEx;
	step = 0;
	for (int ii=0;ii<numEx;ii++)
	{
		rs400_decode_string(u.exo[ii].name,buf+8+step,10);
		rs400_decode_string(u.exo[ii].description,buf+18+step,20);

		u.exo[ii].num_zones = buf[40+step]%0x10;
		u.exo[ii].active_zonesTargets=u.exo[ii].num_zones;
		//u.exo[ii].active_zonesTargets = buf[40+step]/0x10;

		u.exo[ii].guideType = buf[38+step];
		u.exo[ii].zones_type = buf[39+step];

		t1 = msb_lsb_to_decimal(buf[42+step], buf[41+step]);;
		t2 = msb_lsb_to_decimal(buf[44+step], buf[43+step]);
		t3 = msb_lsb_to_decimal(buf[46+step], buf[45+step]);
		if (u.exo[ii].guideType==0 || u.exo[ii].guideType==1)
		{
			u.exo[ii].zone1length =hexa_to_same_decimal(t1);
			u.exo[ii].zone2length =hexa_to_same_decimal(t2);
			u.exo[ii].zone3length =hexa_to_same_decimal(t3);
		}
		else
		{
			u.exo[ii].zone1length =t1;
			u.exo[ii].zone2length =t2;
			u.exo[ii].zone3length =t3;
		}

		u.exo[ii].FC1min[0]=buf[47+step];
		u.exo[ii].FC1min[1]=buf[48+step];
		
		u.exo[ii].FC2min[0]=buf[49+step];
		u.exo[ii].FC2min[1]=buf[50+step];

		u.exo[ii].FC3min[0]=buf[51+step];
		u.exo[ii].FC3min[1]=buf[52+step];
		
		u.exo[ii].FC1max[0]=buf[53+step];
		u.exo[ii].FC1max[1]=buf[54+step];
		
		u.exo[ii].FC2max[0]=buf[55+step];
		u.exo[ii].FC2max[1]=buf[56+step];

		u.exo[ii].FC3max[0]=buf[57+step];
		u.exo[ii].FC3max[1]=buf[58+step];

		u.exo[ii].number = buf[60+step];
		step += 53;
	}
}

int _getNumberOfExercises()
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char query[] = { RS400_CMD_GETOVERVIEW };
	RS400_sendbytes(query, sizeof(query));
	RS400_recvbytes(buf);

	//get the number of exercises
	return buf[4];
}

std::string _getHeader(int id)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char query1[] = { RS400_CMD_GETSESSION, id, 0x00, 0x32 }; //just a small header
	RS400_sendbytes(query1, sizeof(query1));
	RS400_recvbytes(buf);

	rs400_session tmp;
	RS400_parse_session_header(buf+4, tmp);

	std::stringstream oss;
	oss<<tmp.day<<"/"<<tmp.month<<"/"<<tmp.year<<", at ";
	oss<<tmp.start_hour<<"h"<<tmp.start_minute<<"min"<<tmp.start_second<<"s";
	return oss.str();	
}

void _deleteExercise(int SelectedExNumber)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char query1[] = {0x6A,SelectedExNumber,0x00,0x32}; //just a small header
	RS400_sendbytes(query1, sizeof(query1));
	RS400_recvbytes(buf);

	unsigned char query2[] = {0x0C, 0xFE, buf[28],buf[29],buf[30],buf[31],buf[32],0xFF};
	RS400_sendbytes(query2, sizeof(query2));
	RS400_recvbytes(buf);
	
	RS400_separate();
}

void _deleteAll()
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char query1[] = {0x6A,0x00,0x00,0x32}; //just a small header
	RS400_sendbytes(query1, sizeof(query1));
	RS400_recvbytes(buf);

	unsigned char query2[] = {0x0C, 0xFF, buf[28],buf[29],buf[30],buf[31],buf[32],0xFF};
	RS400_sendbytes(query2, sizeof(query2));
	RS400_recvbytes(buf);
	
	RS400_separate();
}


void _setEvent(polarLINUXio_event const &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];

	unsigned char when[]={0x00,0x00};
	int_to_msb_lsb(u.numdays, &when[1], &when[0]);

	unsigned char trame0[]={0x5C,0x00,when[0],when[1],0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8A};
	rs400_encode_string(trame0+4,u.eventName,10);
	if (u.isActive==true) trame0[1]=0x20;
	RS400_sendbytes(trame0, sizeof(trame0));
	RS400_recvbytes(buf);
	if (u.isActive==false) setLOGO();
	
	RS400_separate();
}


void _getEvent(polarLINUXio_event &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char query9[] ={0x5A, 0x00, 0x90, 0x01, 0x00, 0x00, 0x1E, 0x00}; //evenement

	RS400_sendbytes(query9, sizeof(query9));
	RS400_recvbytes(buf);
	rs400_decode_string(u.eventName,buf+14,10);
	if (strcmp((char*)u.eventName,"0000000000\0")==0) strncpy((char*)u.eventName,"eventname \0",11);
	
	u.numdays = msb_lsb_to_decimal(buf[13],buf[12]);
	//i think i don't get the point on a specific parameter
	if (buf[11]==0x60 || buf[11]==0x61 || buf[11]==0x20 || buf[11]==0x21) u.isActive=true; else u.isActive=false;
}

/*
void _deleteEvent()
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char trame0[]={0x5C,0x00,0x00,0x00,0x8A,0x8A,0x8A,0x8A,0x8A,0x8A,0x8A,0x8A,0x8A,0x8A};

	RS400_sendbytes(trame0, sizeof(trame0));
	RS400_recvbytes(buf);

	setLOGO();
}
*/

void setLOGO()
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char logo[]={	0x0F,0x80,0x40,0x00,0x00,0x00,0x00,0x00,
	0x00,0x12,0x94,0x82,0x12,0x95,0x82,0x1e,
	0x95,0xa2,0x0c,0x95,0xa2,0x0c,0x96,0xa2,
	0x1e,0x96,0xa2,0x12,0x96,0xa2,0x02,0xf4,
	0xae,0x00,0x00,0x00,0x11,0x11,0x11,0x24,
	0x92,0x4a,0x15,0x55,0x55,0x3f,0xff,0xff};
	RS400_sendbytes(logo, sizeof(logo));
	RS400_recvbytes(buf);
	
	RS400_separate();
}


void setLOGOnew()
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char msb,lsb;

	unsigned char trame0[]={0x59,0xAC,0x00,0x00,0x77,0x3A,0x00,0x00,
	0xFF,0x3F,0xFF,0xFB,0x3F,0x7C,0xB7,0x3F,0x70,0xFF,0x1F,0xE3,0xEF,0x3F,0xAF,0xFD,
	0x2F,0xEB,0xFF,0x2F,0xA9,0xF7,0x3F,0xE8,0xE5,0x37,0xA8,0xF7,0x37,0xEA,0xFF,0x3B,
	0xE3,0xFD,0x3B,0xA7,0xAF,0x2E,0xFF,0xFB,0x39,0xFE,0xD7,0x3D,0xF2,0xF7,0x38,0xE2,
	0xE7,0x36,0xEA,0xAD,0x3E,0xEA,0x97,0x1F,0x2A,0xAF,0x2E,0xEA,0x83,0x23,0xEA,0xE7,
	0x37,0xE8,0xFF,0x27,0xE8,0xF9,0x2F,0xED,0xFB,0x30,0x7F,0xFF,0x15,0x7F,0xFE,0x35};

	RS400_sendbytes(trame0, sizeof(trame0));
	RS400_recvbytes(buf);

	int baseaddr=msb_lsb_to_decimal(0x3A,0x77);

	int addr=baseaddr+sizeof(trame0)-8;
	int_to_msb_lsb(addr, &msb, &lsb);

	unsigned char trame1[]={0x59,0xAC,0x00,0x00,lsb,msb,0x00,0x00,
	0x73,0xFF,0x1F,0xE3,0xFF,0x3F,0xEB,0xFF,0x3F,0xFB,0xFF,0x3C,0x7B,0xFF,0x1F,0x7B,
	0xFF,0x30,0x7B,0xFF,0x3F,0xF8,0xFE,0x3F,0xE0,0xFF,0x3F,0xE1,0xFE,0x2F,0xFF,0xFF,
	0x2F,0xFC,0xFD,0x37,0xF0,0xFA,0x2F,0xE2,0xFF,0x1C,0xEE,0xE1,0x3E,0x2E,0x9B,0x3E,
	0x6E,0xEB,0x3E,0xEE,0x8E,0x3E,0xAE,0xED,0x3D,0xEC,0xF6,0x3D,0x60,0xBF,0x3F,0xE3,
	0xDF,0x3B,0xBF,0xFF,0x3E,0xFC,0xFF,0x3F,0xB0,0xBF,0x2F,0xE2,0xFF,0x3F,0xEE,0xFF,
	0x3F,0xEE,0xBF,0x3F,0x6E,0xFB,0x3F,0xEE,0xFF,0x3D,0xEE,0xFF,0x3F,0xEC,0xFF,0x3F,
	0xE0,0xDD,0x3E,0xE3,0xFF,0x3F,0xFF,0xEF,0x3F,0xFF,0xFF,0x96,0x0B,0x00,0x00};

	RS400_sendbytes(trame1, sizeof(trame1));
	RS400_recvbytes(buf);
	
	RS400_separate();

}



void _setReminders(polarLINUXio_reminders const &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];

	//set reminders' content
	int baseaddr=msb_lsb_to_decimal(0x01,0xB7);
	unsigned char msb,lsb;

	unsigned char oneReminder[21];
	unsigned char command[] = {0x59,0xAC,0x00,0x00,0xB7,0x01,0x00,0x00};

	for (int i=0;i<7;i++)
	{
		int addr=baseaddr+21*i;
		int_to_msb_lsb(addr, &msb, &lsb);
		memcpy(buf,command,sizeof(command));
		buf[4]=lsb;
		buf[5]=msb;
		memcpy(oneReminder,u.rem[i].date,2);
		memcpy(oneReminder+2,u.rem[i].time,2);
		rs400_encode_string(oneReminder+8,u.rem[i].name,10);
		oneReminder[18] = u.rem[i].repeatMode;
		oneReminder[19] = decimal_to_same_hexa(u.rem[i].repeatExercise);
		oneReminder[20] = u.rem[i].remindAt+u.rem[i].bipstyle;
		memcpy(buf+8,oneReminder,sizeof(oneReminder));

		RS400_sendbytes(buf, 8+sizeof(oneReminder));
		RS400_recvbytes(buf);
		//std::cout<<"one reminder="<<std::endl;
		//displaybuf(buf,8+21);
	}

	//set active reminders
	std::vector<int> whichOne;

	for ( int i=0;i<7;i++)
	{
		if (u.rem[i].active==1) whichOne.push_back(i);
	}
	
	unsigned char emptyBase[]={0x59,0xAC,0x00,0x00,0x4A,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
	unsigned char checksum=0x10;

	for (unsigned i=0;i<whichOne.size();i++)
	{
		checksum--;
		emptyBase[8+i]=whichOne[i];
	}
	emptyBase[8+whichOne.size()]=checksum;
	emptyBase[15]=whichOne.size();
	RS400_sendbytes(emptyBase, sizeof(emptyBase));
	RS400_recvbytes(emptyBase);
	//std::cout<<"checksum="<<std::endl;
	//displaybuf(emptyBase,sizeof(emptyBase));
	RS400_separate();
}


void _getReminders(polarLINUXio_reminders &u)
{
	unsigned char buf[RS400_MAX_PACKET_SIZE];
	unsigned char query10[] ={0x5A, 0x00, 0xB7, 0x01, 0x00, 0x00, 0x9A, 0x00}; //reminders
	RS400_sendbytes(query10, sizeof(query10));
	RS400_recvbytes(buf);

	for (int i=0;i<7;i++)
	{
		unsigned char val = buf[0x93+6+i];
		if ( val > 7) break;
		u.rem[val].active = 0x01;
	}
	
	for (int i=0;i<7;i++)
	{
		polarLINUXio_reminder *p=&u.rem[i];
		rs400_decode_string(p->name,buf+14+21*i,10);

		p->repeatMode = buf[24+21*i]; //one time, every day etc
		p->repeatExercise = hexa_to_same_decimal(buf[25+21*i]); //exercise to do

		p->remindAt = buf[26+21*i]%0x10; //at time, 10 minutes, 30, 1h before
		p->bipstyle = buf[26+21*i]-p->remindAt;//repeatstyle: 0x80=normal, 0x20=silent, 0x40=sound

		p->active = 0x00;
		p->date[0] = buf[6+21*i];
		p->date[1] = buf[7+21*i];
		p->time[0] = buf[8+21*i];
		p->time[1] = buf[9+21*i];
		

		if (strcmp((char*)p->name,"0000000000\0")==0)
		{
			std::ostringstream out;
			out << "remind "<<i;
			std::string namestd = out.str();
			namestd.resize (10,' ');
			strncpy((char*)p->name,namestd.c_str(),11);
			p->active = 0;
			p->repeatExercise = 0;
			p->bipstyle = 0x80;
			p->repeatMode = 0x01;
			p->remindAt = 0x00;

			unsigned char dd,mm,yy;
			dd=01;
			mm=01;
			yy=00;
			ddmmyy2hex(dd,mm,yy,&p->date[0],&p->date[1]);
			
			p->time[1] = 0; //decimal_to_same_hexa(10);
			p->time[0] = 0; //decimal_to_same_hexa(30);
		}
	}
}



void _setAdvancedExos(polarLINUXio_advanced_exercises_list const &u)
{
/*
unsigned char name[]="Exerciceaa";
unsigned char desc[]="description";
unsigned char p[]="General";
unsigned char q[]="Echauffeme";
unsigned char durationtype=01;//1=manual,2=hour,3 distance,4=inc FC, 5=dec FC
unsigned char guidetype = 0x15; //0x15=HR,0x04=free,0x18=sportZone,0x34=pace,0x24=speed 
unsigned char repeatNUM=01;//repeat n times
unsigned char repeatWhat=01;//repeat starting from which zone? (equals 00 for the first "zone")
unsigned char duration1=15; //minutes
unsigned char duration2=10; //seconds
unsigned char FCrange[]={65,85}; //{0,0} for free style
unsigned char FClow[]={65,00};
unsigned char FCHigh[]={85,00}; //high element is divided by 255 to give tenths, for speed. For pace, 1s/km=10.f
unsigned char t18[]={
0x59,0xAC,0x00,0x00,0xDD,0x0A,0x00,0x00\
,0x01,0x81,name[],name[],name[],name[],name[],name[],name[],name[],name[],name[],desc[],desc[],desc[],desc[]\
,desc[],desc[],desc[],desc[],desc[],desc[],desc[],desc[],desc[],desc[],desc[],desc[],desc[],desc[],desc[],0xB2\
,0x2B,0x15,0x23,0x17,0x15,0x00,0x2C,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\
,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x07,0x00,0x04,0x00,0x00,0x00,0x01,p[]\
,p[],p[],p[],p[],p[],p[],0x0A,0x0A,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x20\
,0xE8,0x03,0x01,0x00,q[],q[],q[],q[],q[],q[],q[],q[],q[],q[],durationtype,guidetype\
,repeatNUM,repeatWhat,duration2,duration1,FClow[0],FClow[1],FCHigh[0],FCHigh[1],0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\
,0x00,0x00};

*/
	unsigned char lsb,msb;
	unsigned char totalbuf[RS400_MAX_PACKET_SIZE],buf[RS400_MAX_PACKET_SIZE],buf2[RS400_MAX_PACKET_SIZE];

//set the number of trainings
	unsigned char query16[] ={0x59,0xAC,0x00,0x00,0xF2,0x03,0x00,0x00,u.size()};
	RS400_sendbytes(query16, sizeof(query16));
	RS400_recvbytes(buf);


	memset(totalbuf,0,RS400_MAX_PACKET_SIZE);

	unsigned char *p0, *pb;
	for (int i0=0;i0<u.size();i0++)
	{
		p0=totalbuf+2+0x144*i0;
		rs400_encode_string(p0,u.exo[i0].name,10);
		rs400_encode_string(p0+10,u.exo[i0].desc,20);
		p0[60]=u.exo[i0].numPhases;
		rs400_encode_string(p0+61,u.exo[i0].desc2,10);
		for (int i=0;i<u.exo[i0].numPhases;i++)
		{
			pb=p0+82+i*20;
			const phase *p=&(u.exo[i0].p[i]);
			rs400_encode_string(pb,p->phasename,10);
			pb[10]=p->durationtype;
			pb[11]=p->guidetype; 
			pb[12]=p->repeatNUM;
			pb[13]=p->repeatWhat;
			pb[14]=p->duration2;
			pb[15]=p->duration1;
			pb[16]=p->FClow[0];
			pb[17]=p->FClow[1];
			pb[18]=p->FCHigh[0];
			pb[19]=p->FCHigh[1];
		}
	}

	int nbchar=0x144*u.size();
	int nbframes = nbchar/64;
	int lastframesize = nbchar-nbframes*64;
	int baseaddr=msb_lsb_to_decimal(0x0A,0xDD);

	int addr=baseaddr;
	for (int i=0;i<nbframes;i++)
	{
		int_to_msb_lsb(addr, &msb, &lsb);
		unsigned char trame[]={0x59,0xAC,0x00,0x00,lsb,msb,0x00,0x00};
		memcpy(buf,trame,sizeof(trame));
		memcpy(buf+8,totalbuf+i*64,64);
		RS400_sendbytes(buf, 8+64);
		RS400_recvbytes(buf2);
		addr+=64;
	}
		int_to_msb_lsb(addr, &msb, &lsb);
		unsigned char trame[]={0x59,0xAC,0x00,0x00,lsb,msb,0x00,0x00};
		memcpy(buf,trame,sizeof(trame));
		memcpy(buf+8,totalbuf+nbframes*64,lastframesize);
		RS400_sendbytes(buf, 8+lastframesize);
		RS400_recvbytes(buf2);
		
	RS400_separate();
}


void _getAdvancedExos(polarLINUXio_advanced_exercises_list &u)
{
	unsigned char lsb,msb;

	unsigned char totalbuf[RS400_MAX_PACKET_SIZE],buf[RS400_MAX_PACKET_SIZE];
	unsigned char query16[] ={0x5A, 0x00, 0xF2, 0x03, 0x00, 0x00, 0x01, 0x00}; //Number of exercises
//	printreponse(query16,sizeof(query16));

	RS400_sendbytes(query16, sizeof(query16));
	RS400_recvbytes(buf);
	int numEx=buf[6];

	u.exo.resize(numEx);
	
	int nbchar=0x144*numEx;
	int nbF2=nbchar/0xF2;
	int baseaddr=msb_lsb_to_decimal(0x0A,0xDD);
	for (int i=0;i<nbF2;i++)
	{
		int addr=baseaddr+i*0xF2;
		int_to_msb_lsb(addr, &msb, &lsb);
		unsigned char question[] ={0x5A, 0x00, lsb, msb, 0x00, 0x00, 0xF2, 0x00};
		RS400_sendbytes(question, sizeof(question));
		RS400_recvbytes(buf);
		memcpy(totalbuf+i*0xF2,buf+8,0xF2);
	}
	int addr=baseaddr+nbF2*0xF2;
	int_to_msb_lsb(addr, &msb, &lsb);
	unsigned char question2[] ={0x5A, 0x00, lsb, msb, 0x00, 0x00, 0x52, 0x00};
	RS400_sendbytes(question2, sizeof(question2));
	RS400_recvbytes(buf);
	memcpy(totalbuf+nbF2*0xF2,buf+8,0x52);


	phase *p;
	unsigned char *p0, *pb;

	for (int i0=0;i0<numEx;i0++)
	{
		p0=totalbuf+0x144*i0;
		rs400_decode_string(u.exo[i0].name,p0,10);
		rs400_decode_string(u.exo[i0].desc,p0+10,20);
		u.exo[i0].numPhases=p0[60];
		rs400_decode_string(u.exo[i0].desc2,p0+61,10);	

		for (int i=0;i<u.exo[i0].numPhases;i++)
		{
			pb=p0+82+i*20;
			p=&(u.exo[i0].p[i]);
			rs400_decode_string(p->phasename,pb,10);
			p->durationtype=pb[10];
			p->guidetype=pb[11]; 
			p->repeatNUM=pb[12];
			p->repeatWhat=pb[13];
			p->duration2=pb[14];
			p->duration1=pb[15];
			p->FClow[0]=pb[16];
			p->FClow[1]=pb[17];
			p->FCHigh[0]=pb[18];
			p->FCHigh[1]=pb[19];
		}
	}

/*
unsigned char name[11];
unsigned char desc[21];
unsigned char p[11];

unsigned char phasename[11];
unsigned char durationtype; //=01;//1=manual,2=hour,3 distance,4=inc FC, 5=dec FC
unsigned char guidetype; // = 0x15; //0x15=HR,0x04=free,0x18=sportZone,0x34=pace,0x24=speed 
unsigned char repeatNUM; //=01;//repeat n times
unsigned char repeatWhat; //=01;//repeat starting from which zone? (equals 00 for the first "zone")
unsigned char duration1; //=15; //minutes
unsigned char duration2; //=10; //seconds
unsigned char FCrange[2]; //={65,85}; //{0,0} for free style
unsigned char FClow[2]; //={65,00};
unsigned char FCHigh[2]; //={85,00}; //high element is divided by 255 to give tenths, for speed. For pace, 1s/km=10.f
*/


}


void _setTraining(polarLINUXio_advanced_exercises_list const &u)
{
	unsigned char lsb,msb;
	unsigned char totalbuf[RS400_MAX_PACKET_SIZE],buf[RS400_MAX_PACKET_SIZE],buf2[RS400_MAX_PACKET_SIZE];

//set the number of trainings
	unsigned char query16[] ={0x59,0xAC,0x00,0x00,0xF3,0x03,0x00,0x00,u.size()};
	RS400_sendbytes(query16, sizeof(query16));
	RS400_recvbytes(buf);

	memset(totalbuf,0,RS400_MAX_PACKET_SIZE);	


	unsigned char *p0, *pb;
	for (int i0=0;i0<u.size();i0++)
	{
		p0=totalbuf+2+0x144*i0;
		rs400_encode_string(p0,u.exo[i0].name,10);
		rs400_encode_string(p0+10,u.exo[i0].desc,20);
		p0[60]=u.exo[i0].numPhases;
		rs400_encode_string(p0+61,u.exo[i0].desc2,10);

		ddmmyy2hex(u.exo[i0].date[0],u.exo[i0].date[1], u.exo[i0].date[2],&p0[30],&p0[31]);
		p0[32]=decimal_to_same_hexa(u.exo[i0].minute);
		p0[33]=decimal_to_same_hexa(u.exo[i0].hour);

		for (int i=0;i<u.exo[i0].numPhases;i++)
		{
			pb=p0+82+i*20;
			const phase *p=&(u.exo[i0].p[i]);
			rs400_encode_string(pb,p->phasename,10);
			pb[10]=p->durationtype;
			pb[11]=p->guidetype; 
			pb[12]=p->repeatNUM;
			pb[13]=p->repeatWhat;
			pb[14]=p->duration2;
			pb[15]=p->duration1;
			pb[16]=p->FClow[0];
			pb[17]=p->FClow[1];
			pb[18]=p->FCHigh[0];
			pb[19]=p->FCHigh[1];
		}
	}

	int nbchar=0x144*u.size();
	int nbframes = nbchar/64;
	int lastframesize = nbchar-nbframes*64;
	int baseaddr=msb_lsb_to_decimal(0x17,0x85);

	int addr=baseaddr;
	for (int i=0;i<nbframes;i++)
	{
		int_to_msb_lsb(addr, &msb, &lsb);
		unsigned char trame[]={0x59,0xAC,0x00,0x00,lsb,msb,0x00,0x00};
		memcpy(buf,trame,sizeof(trame));
		memcpy(buf+8,totalbuf+i*64,64);
		RS400_sendbytes(buf, 8+64);
		RS400_recvbytes(buf2);
		addr+=64;
	}
		int_to_msb_lsb(addr, &msb, &lsb);
		unsigned char trame[]={0x59,0xAC,0x00,0x00,lsb,msb,0x00,0x00};
		memcpy(buf,trame,sizeof(trame));
		memcpy(buf+8,totalbuf+nbframes*64,lastframesize);
		RS400_sendbytes(buf, 8+lastframesize);
		RS400_recvbytes(buf2);
		
	RS400_separate();
}


void _getTraining(polarLINUXio_advanced_exercises_list &u)
{
//same as advanced exos
//address differs + date and time

//get the number of trainings
	unsigned char lsb,msb;
	unsigned char totalbuf[RS400_MAX_PACKET_SIZE],buf[RS400_MAX_PACKET_SIZE];
	unsigned char query16[] ={0x5A, 0x00, 0xF3, 0x03, 0x00, 0x00, 0x01, 0x00}; //Number of exercises
	RS400_sendbytes(query16, sizeof(query16));
	RS400_recvbytes(buf);
	int numEx=buf[6];

	u.exo.resize(numEx);

	int nbchar=0x144*numEx;
	int nbF2=nbchar/0xF2;
	int baseaddr=msb_lsb_to_decimal(0x17,0x85);
	for (int i=0;i<nbF2;i++)
	{
		int addr=baseaddr+i*0xF2;
		int_to_msb_lsb(addr, &msb, &lsb);
		unsigned char question[] ={0x5A, 0x00, lsb, msb, 0x00, 0x00, 0xF2, 0x00};
		RS400_sendbytes(question, sizeof(question));
		RS400_recvbytes(buf);
		memcpy(totalbuf+i*0xF2,buf+8,0xF2);
	}
	int addr=baseaddr+nbF2*0xF2;
	int_to_msb_lsb(addr, &msb, &lsb);
	unsigned char question2[] ={0x5A, 0x00, lsb, msb, 0x00, 0x00, 0x52, 0x00};
	RS400_sendbytes(question2, sizeof(question2));
	RS400_recvbytes(buf);
	memcpy(totalbuf+nbF2*0xF2,buf+8,0x52);

	phase *p;
	unsigned char *p0, *pb;

	for (int i0=0;i0<numEx;i0++)
	{
		p0=totalbuf+0x144*i0;
		rs400_decode_string(u.exo[i0].name,p0,10);
		rs400_decode_string(u.exo[i0].desc,p0+10,20);
		u.exo[i0].numPhases=p0[60];
		//std::cout<<"numphases = "<<(int)u.exo[i0].numPhases<<std::endl;
		rs400_decode_string(u.exo[i0].desc2,p0+61,10);
		//for (int i=0;i<40;i++) printf("%0x ",(int)p0[i]);
//	printf("\n");

		hex2ddmmyy(p0[30],p0[31],&u.exo[i0].date[0],&u.exo[i0].date[1],&u.exo[i0].date[2]);
		u.exo[i0].minute=hexa_to_same_decimal(p0[32]);
		u.exo[i0].hour=hexa_to_same_decimal(p0[33]);

		for (int i=0;i<u.exo[i0].numPhases;i++)
		{
			pb=p0+82+i*20;
			p=&(u.exo[i0].p[i]);
			rs400_decode_string(p->phasename,pb,10);
			p->durationtype=pb[10];
			p->guidetype=pb[11]; 
			p->repeatNUM=pb[12];
			p->repeatWhat=pb[13];
			p->duration2=pb[14];
			p->duration1=pb[15];
			p->FClow[0]=pb[16];
			p->FClow[1]=pb[17];
			p->FCHigh[0]=pb[18];
			p->FCHigh[1]=pb[19];
		}
	}

}
